<template>
    <div ref = "statsRef"></div>
    <div ref ="containerRef" class="container"></div>
</template>

<script setup lang="ts">
import { AxesHelper, BoxGeometry, Color, Fog, Mesh, MeshBasicMaterial, MeshLambertMaterial, PerspectiveCamera, PlaneGeometry, Scene, SphereGeometry, SpotLight, WebGLRenderer } from "three";
import {onMounted, ref, render} from "vue";
import Stats from 'stats.js';
import * as dat from 'dat.gui';

const stats = new Stats();
stats.showPanel(0)

const statsRef = ref<HTMLElement>();
const containerRef = ref<HTMLElement>();


// 创建场景
const scene = new Scene();
// 创建摄像机，并设置位置
const camera= new PerspectiveCamera(45, window.innerWidth/window.innerHeight,0.1,1000);
camera.position.set(-30,40,30);
// 设置摄像机朝向
camera.lookAt(scene.position)

// 创建渲染器
const renderer= new WebGLRenderer()
renderer.setClearColor(new Color(0xeeeeee))
renderer.setSize(window.innerWidth,window.innerHeight)
renderer.shadowMap.enabled = true


const controlRef = ref({
    rotationSpeed : 0.02,
    bouncingSpeed : 0.02,
    numberOfObjects:scene.children.length,
    addCube: function(){
        const cubeGeom = new BoxGeometry(4,4,4)
        const cubeMaterial = new MeshLambertMaterial({color:0xff0000,wireframe:false})
        const cube = new Mesh(cubeGeom,cubeMaterial)
        cube.name = "cube-" + scene.children.length
        cube.castShadow = true

        cube.position.x=-30+Math.round(Math.random()*60)
        cube.position.y=Math.round(Math.random()*5)
        cube.position.z=-20+Math.round(Math.random()*40)

        scene.add(cube); 
        this.numberOfObjects = scene.children.length
    },
    removeCube: function(){
        const  allChildren = scene.children;
        const lastChild = allChildren[allChildren.length-1];
        if(lastChild instanceof Mesh && lastChild.name.startsWith("cube")){
            scene.remove(lastChild)
            this.numberOfObjects = scene.children.length
        }
    },
    addFog: function(){
        const fog = new Fog(0xffffff,0.015,100)
        fog.name = "fog"
        scene.fog = fog
        this.numberOfObjects = scene.children.length
    },
    removeFog: function(){
        scene.fog = null;
        this.numberOfObjects = scene.children.length
    }
}) 
if(document.querySelectorAll(".dg.ac>.dg.main.a").length===0){
    const gui = new dat.GUI();
    gui.add(controlRef.value,"numberOfObjects").listen();
    gui.add(controlRef.value,"addCube");
    gui.add(controlRef.value,"removeCube");
    gui.add(controlRef.value,"addFog");
    gui.add(controlRef.value,"removeFog");
    gui.add(controlRef.value,"rotationSpeed",0,0.5);
    gui.add(controlRef.value,"bouncingSpeed",0,0.5);
}

// 添加灯光
const spotLight = new SpotLight(0xffffff);
spotLight.castShadow= true;
spotLight.position.set(-40,60,-10);
scene.add(spotLight)

onMounted(() => {
    
    stats.dom.style.top="50px";
    statsRef.value?.append(stats.dom)
    containerRef.value?.appendChild(renderer.domElement)
    renderer.render(scene,camera)
})

// 添加坐标轴
const axes = new AxesHelper(20)
scene.add(axes)

const planeGeom = new PlaneGeometry(60,20)
const meshMaterial = new MeshLambertMaterial({color: 0xcccccc})
const plane = new Mesh(planeGeom,meshMaterial)
plane.position.x=15
plane.position.y=0
plane.position.z=0
plane.rotation.x = -0.5 * Math.PI
plane.receiveShadow = true
scene.add(plane);

const cubeGeom = new BoxGeometry(4,4,4)
const cubeMaterial = new MeshLambertMaterial({color:0xff0000,wireframe:false})
const cube = new Mesh(cubeGeom,cubeMaterial)
cube.castShadow = true

cube.position.set(2,2,2)

scene.add(cube);

const sphereGeom = new SphereGeometry(4)
const sphereMaterial = new MeshLambertMaterial({color:0x7777ff,wireframe:false})
const sphere = new Mesh(sphereGeom,sphereMaterial)
sphere.castShadow = true

sphere.position.x=20
sphere.position.y=4
sphere.position.z=2

scene.add(sphere);

let step = 0;

function renderScene() {
    stats.update();
    scene.traverse(e=>{
        if(e.name.startsWith("cube")){
            e.rotation.x += controlRef.value.rotationSpeed;
            e.rotation.y += controlRef.value.rotationSpeed;
            e.rotation.z += controlRef.value.rotationSpeed;
        }
    })
    cube.rotation.x += controlRef.value.rotationSpeed;
    cube.rotation.y += controlRef.value.rotationSpeed;
    cube.rotation.z += controlRef.value.rotationSpeed;

    step+= controlRef.value.bouncingSpeed;
    sphere.position.x = 20+10*Math.cos(step)
    sphere.position.y = 2+10*Math.abs(Math.sin(step))

    requestAnimationFrame(renderScene)
    renderer.render(scene,camera)
}
renderScene()


window.addEventListener('resize',()=>{
    camera.aspect = window.innerWidth/window.innerHeight
    // 更新相机投影矩阵
    camera.updateProjectionMatrix()
    renderer.setSize(window.innerWidth,window.innerHeight)
},false)
</script>

<style scoped>
    .tab{
        width:100px
    }
</style>
